#include "fxcc/core/graph/opengl3/ImGuiGlfwApp.h"
#include "fxcc/core/graph/common/Geometry.h"
#include "fxcc/core/graph/opengl3/MeshJack.h"

#include "fxcc/imgui/Editor.h"
#include "fxcc/core/graph/opengl3/phong/Effect3d.h"
#include "fxcc/core/AssertManager.h"

using namespace fxcc::platform;
using namespace fxcc::graph;
using namespace fxcc::graph::opengl3;
using namespace fxcc::imgui::graph::opengl3;
using BaseApp = fxcc::imgui::graph::opengl3::GlfwApp;

#undef main

struct SimpleApp : public BaseApp
{
public:
    std::shared_ptr<fxcc::graph::opengl3::RenderTargetJack> m_RenderTarget;

    glm::vec4 color;
    fxcc::graph::common::Transform transform;
    std::shared_ptr < fxcc::graph::opengl3::phong::Effect3d> m_PhongEffect;

    fxcc::graph::common::LightEffect m_LightEffect;
    phong::Material m_PhongMaterial;

    std::shared_ptr<fxcc::graph::opengl3::MeshJack> m_CubeMesh;

    fxcc::graph::common::Camera camera;

    SimpleApp(const fxcc::platform::common::App::Desc& desc) : BaseApp(desc), color(1.0)
    {
    }
    bool Init() override
    {
        if (!BaseApp::Init())
        {
            return false;
        }

        if (!InitResources())
        {
            return false;
        }
        return true;
    };

    void printOpenGLESVersion()
    {
        const char* version = (const char*)glGetString(GL_VERSION);
        std::cout << "OpenGL ES Version: " << version << std::endl;
    };


    bool InitResources()
    {
        camera.SetPosition(glm::vec3(5.0f));
        camera.LookAt(glm::vec3(0.0f));

        m_PhongEffect = std::make_shared<fxcc::graph::opengl3::phong::Effect3d>();

        m_LightEffect.numDirlights = 1;

        auto& am = fxcc::AssertManager::Inst();

        auto geoData = fxcc::graph::common::Geometry::CreateBox();
        m_CubeMesh = std::make_shared<fxcc::graph::opengl3::MeshJack>(geoData);

        std::string _d = am.GetFile("Model/Sponza");

        for (const auto it : fs::directory_iterator(_d))
        {
            fxcc::graph::common::Texture2DJack::Desc desc;
            desc.SetPath(it.path().string());
        }
        return true;
    };

    fxcc::imgui::Editor editor;

    void OnEdit() override
    {
        ImGui::DockSpaceOverViewport(0, ImGui::GetMainViewport());

        ImGui::Begin("Phong Effect");
        fxcc::imgui::Editor editor;
        editor.EditInst<fxcc::graph::common::LightEffect>("lightEffect", m_LightEffect);

        editor.EditInst<fxcc::graph::opengl3::phong::Material>("material", m_PhongMaterial);
        editor.EditInst<fxcc::graph::common::Transform>("transform", transform);
        ImGui::End();

        ImGui::Begin("Frame");
        editor.AddFrameBuffer(m_RenderTarget->m_Textures[0]->GetTextureId());
        ImGui::End();

        fxcc::graph::opengl3::RenderStates::Inst();



    }
    void OnDestroy() override
    {

        BaseApp::OnDestroy();
    }
    void OnFrameRender() override
    {
        glViewport(0, 0, m_Desc.m_Size.x, m_Desc.m_Size.y);

        glClearColor(color.x, color.y, color.z, color.w);
        glClear(GL_COLOR_BUFFER_BIT);

        m_RenderTarget->Begin();
        m_RenderTarget->ClearColor(color);
        m_RenderTarget->ClearBuffer(1, 1);

        m_PhongEffect->Begin();
        m_PhongEffect->SetFixed();
        m_PhongEffect->SetCamera(camera);
        m_PhongEffect->SetLightEffect(m_LightEffect);
        m_PhongEffect->SetMaterial(m_PhongMaterial);
        m_PhongEffect->SetObjData(transform);
        m_PhongEffect->InstMeshJack(m_CubeMesh.get());
        m_PhongEffect->End();

        m_RenderTarget->End();
    };

    void OnFramebuffersize(int w, int h) override
    {
        opengl3::GlfwApp::OnFramebuffersize(w, h);
        camera.SetAspect(m_Desc.Aspect());

        m_RenderTarget = std::make_shared<fxcc::graph::opengl3::RenderTargetJack>(RenderTargetJack::Desc(1, { w, h, 4,0 }));
    }

    void OnUpdate() override
    {
        opengl3::GlfwApp::OnUpdate();

        float ctTime = m_GlfwlTimer.m_CurrentTime;
        camera.FreeMove(m_Input, m_GlfwlTimer.m_DeltaTime);

        float deltaTime = m_GlfwlTimer.m_DeltaTime;


    }
};

int main()
{
    ztclog::pushFunction([](const ztclog::Line& line)
        {
            if (line.m_Type != ztclog::Line::Type::_line_debug_)
            {
                std::cout << line.m_Text << std::endl;
            } });

            using _App = SimpleApp;
            using _Desc = fxcc::platform::common::App::Desc;

            _Desc desc;
            desc.m_Pos = glm::ivec2(100, 100);
            desc.m_Size = glm::ivec2(900, 600);
            desc.m_ScaleFactor = 1.0f;

            desc.m_Title = "test phong app";
            std::shared_ptr<_App> _app = std::make_shared<_App>(desc);
            return _app->Run();
};
